<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Fancy Robots
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora160.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora162.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Fancy Robots</H2>
<A NAME="app-robot"></A>The example in this section illustrates the use of objects from the
graphics library. We will revisit the concepts of simple
inheritance, overriding methods and dynamic dispatch. We also
see how parametric classes may be profitably used.<BR>
<BR>
The application recognizes two principal categories of objects: a
world and robots. The world represents a state space within which
the robots evolve. We will have various classes of robots, each
possessing its own strategy to move around in the world.<BR>
<BR>
The principle of interaction between robots and the world here is
extremely simple. The world is completely in control of the game: it
asks, turn by turn, each of the robots if they know their next
position. Each robot determines its next position fairly blindly. They
do not know the geometry of the world, nor what other robots may be
present. If the position requested by a robot is legal and open, the
world will place the robot at that position.<BR>
<BR>
The world displays the evolution of the robots via an interface.
The (relative) complexity of the conception and development of this
example is in the always-necessary separation between a behavior
(here the evolution of the robots) and its interface (here the
tracking of this evolution).<BR>
<BR>

<H5> General Description</H5>
The application is developed in two stages.
<OL type=1>
<LI> A group of definitions providing pure calculation classes for
the world and for the diverse set of envisaged robots.<BR>
<BR>

<LI> A group of definitions using the preceding set, adding whatever
is necessary to add in an interface.<BR>
<BR>
We provide two examples of such interfaces: a rudimentary text-based
interface, and a more elaborate one using a graphical library.</OL>In the first section, we provide the <I>abstract</I> definitions for
the robots. Then (page <A HREF="book-ora161.html#wch">??</A>), we provide the pure abstract
definition for the world. In the next section (page <A HREF="book-ora161.html#trch">??</A>), we introduce the
text interface for the robots, and in the fourth section (page <A HREF="book-ora161.html#twch">??</A>), the interface for
the world. On page <A HREF="book-ora161.html#grch">??</A> we introduce a graphical interface
for the robots and finally (page <A HREF="book-ora161.html#gwch">??</A>) we define a world for the
graphical interface.<BR>
<BR>
<A NAME="toc235"></A>
<H3> ``Abstract'' Robots</H3>
<A NAME="subsec-rch"></A>The first thing to do is to examine robots abstractly, independent of
any consideration of the environment in which they will move, that is
to say, the interface that displays them.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>robot<CODE> </CODE><TT>(</TT>i0<CODE>:</CODE>int<TT>)</TT><CODE> </CODE><TT>(</TT>j0<CODE>:</CODE>int<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>i0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_pos<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>set_pos<CODE> </CODE><TT>(</TT>i<CODE>'</CODE><CODE>,</CODE><CODE> </CODE>j<CODE>'</CODE><TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>i<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>i<CODE>'</CODE>;<CODE> </CODE>j<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>j<CODE>'</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>next_pos<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
A robot is an entity which knows, or believes it knows, its position
(<TT>i</TT> and <TT>j</TT>), is capable of communicating that position
to a requester (<TT>get_pos</TT>), is able to modify this knowledge
if it knows precisely where it should be (<TT>set_pos</TT>) and may
decide to move towards a new position (<TT>next_pos</TT>).<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV> 
<DIV ALIGN=center>
<IMG SRC="book-ora074.gif">
<BR>
<BR>
<DIV ALIGN=center>Figure 17.9: Hierarchy of pure robot classes</DIV><BR>

<A NAME="fig-rch"></A>
</DIV>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>To improve the readability of the program, we define relative
movements based on absolute directions:<BR>
<BR>


<PRE><BR># <B>type</B><CODE> </CODE>dir<CODE> </CODE><CODE>=</CODE><CODE> </CODE>North<CODE> </CODE><CODE>|</CODE><CODE> </CODE>East<CODE> </CODE><CODE>|</CODE><CODE> </CODE>South<CODE> </CODE><CODE>|</CODE><CODE> </CODE>West<CODE> </CODE><CODE>|</CODE><CODE> </CODE>Nothing<CODE> </CODE><CODE> </CODE>;;<BR><BR># <B>let</B><CODE> </CODE>walk<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>function</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>North<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>+</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><CODE>|</CODE><CODE> </CODE>South<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>-</CODE><CODE>1</CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>West<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>x<CODE>-</CODE><CODE>1</CODE><CODE>,</CODE>y<TT>)</TT><CODE> </CODE><CODE>|</CODE><CODE> </CODE>East<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>x<CODE>+</CODE><CODE>1</CODE><CODE>,</CODE>y<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Nothing<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE>;;<BR><CODE>val walk : int * int -&gt; dir -&gt; int * int = &lt;fun&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>turn_right<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>function</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>North<CODE> </CODE>-&gt;<CODE> </CODE>East<CODE> </CODE><CODE>|</CODE><CODE> </CODE>East<CODE> </CODE>-&gt;<CODE> </CODE>South<CODE> </CODE><CODE>|</CODE><CODE> </CODE>South<CODE> </CODE>-&gt;<CODE> </CODE>West<CODE> </CODE><CODE>|</CODE><CODE> </CODE>West<CODE> </CODE>-&gt;<CODE> </CODE>North<CODE> </CODE><CODE>|</CODE><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>x<CODE> </CODE>;;<BR><CODE>val turn_right : dir -&gt; dir = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The schema is shown by the virtual class <TT>robots</TT> from which we
define four distinct species of robots (see figure
<A HREF="book-ora161.html#fig-rch">17.9</A>) to more precisely see their manner of motion:<BR>
<BR>
<UL>
<LI>
 Fixed robots which never move:


<PRE><BR># <B>class</B><CODE> </CODE>fix_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>next_pos()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>

<LI> Crazy robots which move at random:


<PRE><BR># <B>class</B><CODE> </CODE>crazy_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>next_pos<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE>i<CODE>+</CODE><TT>(</TT>Random.int<CODE> </CODE><CODE>3</CODE><TT>)</TT><CODE>-</CODE><CODE>1</CODE><CODE> </CODE><CODE>,</CODE><CODE> </CODE>j<CODE>+</CODE><TT>(</TT>Random.int<CODE> </CODE><CODE>3</CODE><TT>)</TT><CODE>-</CODE><CODE>1</CODE><CODE> </CODE><TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<CODE> </CODE><BR>

</PRE>
<BR>
<BR>

<LI> Obstinate robots which keep trying to advance in one direction
whenever they are able to do so,<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>obstinate_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>wanted_pos<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i0<CODE>,</CODE>j0<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>dir<CODE> </CODE><CODE>=</CODE><CODE> </CODE>West<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>set_wanted_pos<CODE> </CODE>d<CODE> </CODE><CODE>=</CODE><CODE> </CODE>wanted_pos<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>walk<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE>d<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>change_dir<CODE> </CODE><CODE>=</CODE><CODE> </CODE>dir<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>turn_right<CODE> </CODE>dir<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>next_pos<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>wanted_pos<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><CODE> </CODE><B>let</B><CODE> </CODE>np<CODE> </CODE><CODE>=</CODE><CODE> </CODE>walk<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE>dir<CODE> </CODE><B>in</B><CODE> </CODE><TT>(</TT><CODE> </CODE>wanted_pos<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>np<CODE> </CODE>;<CODE> </CODE>np<CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><TT>(</TT><CODE> </CODE>self#change_dir<CODE> </CODE>;<CODE> </CODE>wanted_pos<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE>;<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>

<LI> Interactive robots which obey the commands of an exterior operator:<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>interactive_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE><B>private</B><CODE> </CODE>get_move<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>dir<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>next_pos<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>walk<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><TT>(</TT>self#get_move<CODE> </CODE>()<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><BR>

</PRE>

</UL>The case of the interactive robot is different from the others in that
its behavior is controlled by an interface that permits communicating
orders to it. To deal with this, we provide a virtual method to
communicate this order. As a consequence, the class
<TT>interactive_robot</TT> remains abstract.<BR>
<BR>
Note that not only do the four specialized robot classes inherit from
class <TT>robot</TT>, but also any others that have the same type.
In effect, the only methods that we have added are the private methods
that therefore do not appear in the type signatures of the instances of
these classes (see page <A HREF="book-ora142.html#subsubsec-private-method">??</A>). This
property is indispensable if we wish to consider all the robots to be
objects of the same type.<BR>
<BR>
<A NAME="toc236"></A>
<H3> Pure World</H3><A NAME="wch"></A>A <EM>pure</EM> world is a world that is independent of an interface. It
is understood as the state space of positions which a robot may
occupy. It takes the form of a grid of size <TT>l</TT> �
<TT>h</TT>, with a method <TT>is_legal</TT> to assure that a
coordinate is a valid position in the world, and a method
<TT>is_free</TT> indicates whether or not a robot occupies a given
position.<BR>
<BR>
In practice, a world manages the list of <TT>robots</TT> present on its surface 
while a method, <TT>add</TT>, allows new robots to enter the world.<BR>
<BR>
Finally, a world is made visible by the method <TT>run</TT>, allowing
the world to come to life.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE>[</CODE><I>'robot_type</I><CODE>]</CODE><CODE> </CODE>world<CODE> </CODE><TT>(</TT>l0<CODE>:</CODE>int<TT>)</TT><CODE> </CODE><TT>(</TT>h0<CODE>:</CODE>int<TT>)</TT><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>l<CODE> </CODE><CODE>=</CODE><CODE> </CODE>l0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>h<CODE> </CODE><CODE>=</CODE><CODE> </CODE>h0<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>robots<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE>[]<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'robot_type</I><CODE> </CODE>list<CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>add<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE>robots<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>r::robots<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>is_free<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>List.for_all<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE>r#get_pos<CODE> </CODE><CODE>&lt;&gt;</CODE><CODE> </CODE>p<TT>)</TT><CODE> </CODE><CODE> </CODE>robots<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>is_legal<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>bool<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>run_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r#next_pos<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>self#is_legal<CODE> </CODE>p<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>self#is_free<CODE> </CODE>p<TT>)</TT><CODE> </CODE><B>then</B><CODE> </CODE>r#set_pos<CODE> </CODE>p<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>run<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><B>true</B><CODE> </CODE><B>do</B><CODE> </CODE>List.iter<CODE> </CODE><TT>(</TT><B>function</B><CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE>self#run_robot<CODE> </CODE>r<TT>)</TT><CODE> </CODE>robots<CODE> </CODE><B>done</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class virtual ['a] world :</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    constraint 'a =</CODE><BR><CODE>      &lt; get_pos : int * int; next_pos : unit -&gt; int * int;</CODE><BR><CODE>        set_pos : int * int -&gt; unit; .. &gt;</CODE><BR><CODE>    val h : int</CODE><BR><CODE>    val l : int</CODE><BR><CODE>    val mutable robots : 'a list</CODE><BR><CODE>    method add : 'a -&gt; unit</CODE><BR><CODE>    method is_free : int * int -&gt; bool</CODE><BR><CODE>    method virtual is_legal : int * int -&gt; bool</CODE><BR><CODE>    method run : unit -&gt; unit</CODE><BR><CODE>    method private run_robot : 'a -&gt; unit</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
The Objective CAML type system does not permit leaving the types of robots
undetermined (see page <A HREF="book-ora143.html#subsec-parameterized-class">??</A>). To
resolve this problem, we might consider restraining the type to those
of the class <TT>robot</TT>. But that would forbid populating a world
with objects other than those having exactly the same type as
<TT>robot</TT>. As a result, we have instead decided to parameterize
<TT>world</TT> with the type of the robots that populate it.
We may thereby instantiate this type parameter with textual robots or
graphical robots.<BR>
<BR>
<A NAME="toc237"></A>
<H3> Textual Robots</H3><A NAME="trch"></A>
<H5> Text Objects</H5>To obtain robots controllable via a textual interface, we define a
class of text objects (<TT>txt_object</TT>).<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>txt_object<CODE> </CODE><TT>(</TT>s0<CODE>:</CODE>string<TT>)</TT><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>name<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_name<CODE> </CODE><CODE>=</CODE><CODE> </CODE>name<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>

<H5> An Interface Class: Abstract Textual Robots</H5>
<A NAME="cspec"></A>By double inheritance from <TT>robots</TT> and <TT>txt_object</TT>,
we obtain the abstract class <TT>txt_robot</TT> of textual robots.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>txt_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>txt_object<CODE> </CODE><CODE>"Anonymous"</CODE><BR><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class virtual txt_robot :</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    val mutable i : int</CODE><BR><CODE>    val mutable j : int</CODE><BR><CODE>    val name : string</CODE><BR><CODE>    method get_name : string</CODE><BR><CODE>    method get_pos : int * int</CODE><BR><CODE>    method virtual next_pos : unit -&gt; int * int</CODE><BR><CODE>    method set_pos : int * int -&gt; unit</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
This class defines a world with a textual interface (see page
<A HREF="book-ora161.html#twch">??</A>). The inhabitants of this world will not be objects of
<TT>txt_robot</TT> (since this class is abstract) nor inheritors of
this class. The class <TT>txt_robot</TT> is, in a way, an
interface classe permitting the compiler to identify
the method types (calculations and interfaces) of the inhabitants of
the text interface world. The use of such a specification class
provides the separation we wish to maintain between calculations and
interface.<BR>
<BR>

<H5> Concrete Text Robots</H5>
These are simply obtained via double inheritance; figure
<A HREF="book-ora161.html#trch-fig">17.10</A> shows the hierarchy of classes.<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV> 
<DIV ALIGN=center>
<IMG SRC="book-ora075.gif">
<BR>
<BR>
<DIV ALIGN=center>Figure 17.10: Hierarchy of classes for text mode robots</DIV><BR>

<A NAME="trch-fig"></A>
</DIV>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>

<PRE><BR># <B>class</B><CODE> </CODE>fix_txt_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>fix_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>txt_object<CODE> </CODE><CODE>"Fix robot"</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE>crazy_txt_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>crazy_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>txt_object<CODE> </CODE><CODE>"Crazy robot"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE>obstinate_txt_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>obstinate_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>txt_object<CODE> </CODE><CODE>"Obstinate robot"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
The interactive robots require, for a workable implementation,
defining their method of interacting with the user.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>interactive_txt_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>interactive_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>txt_object<CODE> </CODE><CODE>"Interactive robot"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>get_move<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"Which dir : (n)orth (e)ast (s)outh (w)est ? "</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>read_line()<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>"n"</CODE><CODE> </CODE>-&gt;<CODE> </CODE>North<CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"s"</CODE><CODE> </CODE>-&gt;<CODE> </CODE>South<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"e"</CODE><CODE> </CODE>-&gt;<CODE> </CODE>East<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"w"</CODE><CODE> </CODE>-&gt;<CODE> </CODE>West<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>Nothing<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
<A NAME="toc238"></A>
<H3> Textual World</H3><A NAME="twch"></A> The text interface world is derived from the pure world by:
<OL type=1>
<LI> Inheritance from the generic class <TT>world</TT> by
instantiating its type parameter with the class specified by
<TT>txt_robot</TT>, and<BR>
<BR>

<LI> Redefinition of the method <TT>run</TT> to include the
different textual methods.</OL>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>txt_world<CODE> </CODE><TT>(</TT>l0<CODE>:</CODE>int<TT>)</TT><CODE> </CODE><TT>(</TT>h0<CODE>:</CODE>int<TT>)</TT><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE>txt_robot<CODE>]</CODE><CODE> </CODE>world<CODE> </CODE>l0<CODE> </CODE>h0<CODE> </CODE><B>as</B><CODE> </CODE>super<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>display_robot_pos<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>r#get_pos<CODE> </CODE><B>in</B><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"(%d,%d)"</CODE><CODE> </CODE>i<CODE> </CODE>j<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>run_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r#next_pos<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>self#is_legal<CODE> </CODE>p<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>self#is_free<CODE> </CODE>p<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>begin</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"%s is moving from "</CODE><CODE> </CODE>r#get_name<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#display_robot_pos<CODE> </CODE>r<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>" to "</CODE><CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>r#set_pos<CODE> </CODE>p;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#display_robot_pos<CODE> </CODE>r<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>begin</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"%s is staying at "</CODE><CODE> </CODE>r#get_name<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#display_robot_pos<CODE> </CODE>r<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_newline<CODE> </CODE>()<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE>"next - "</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>ignore<CODE> </CODE><TT>(</TT>read_line()<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>run<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>print_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"%s is at "</CODE><CODE> </CODE>r#get_name<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#display_robot_pos<CODE> </CODE>r<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_newline<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"Initial state :\n"</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>List.iter<CODE> </CODE>print_robot<CODE> </CODE>robots;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"Running :\n"</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>super#run()<CODE> </CODE><CODE> </CODE><CODE>(* 1 *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
We direct the reader's attention to the call to 
<TT>run</TT> of the ancestor class (this method call is marked <CODE>(* 1 *)</CODE> in the
code) in the redefinition of the same method. There we have an
illustration of the two possible types of method dispatch: static or
dynamic (see page <A HREF="book-ora142.html#subsubsec-liaison-retardee">??</A>). The call to
super#run is static. This is why we name the
superclass: to be able to call the methods when they are
redefined. On the other hand, in super#run we
find a call to self#run_robot. This is a dynamic dispatch;
the method defined in class <TT>txt_world</TT> is executed, not that
of <TT>world</TT>. Were the method from <TT>world</TT> executed,
nothing would be displayed, and the method in <TT>txt_world</TT>
would remain useless.<BR>
<BR>

<H5> The planar rectangular text world</H5> is obtained by
implementing the final method that still remains abstract:
<TT>is_legal</TT>.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>closed_txt_world<CODE> </CODE>l0<CODE> </CODE>h0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>txt_world<CODE> </CODE>l0<CODE> </CODE>h0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>is_legal<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE>0</CODE><CODE>&lt;=</CODE>i<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>i<CODE>&lt;</CODE>l<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT><CODE>0</CODE><CODE>&lt;=</CODE>j<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>j<CODE>&lt;</CODE>h<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV> 
<DIV ALIGN=center>
<IMG SRC="book-ora076.gif">
<BR>
<BR>
<DIV ALIGN=center>Figure 17.11: Hierarchy of classes in the textual planar rectangular world</DIV><BR>

<A NAME="twch-fig"></A>
</DIV>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>We may proceed with a small essay in typing:


<PRE><BR><B>let</B><CODE> </CODE>w<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>closed_txt_world<CODE> </CODE><CODE>5</CODE><CODE> </CODE><CODE>5</CODE><CODE> </CODE><BR><B>and</B><CODE> </CODE>r1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>fix_txt_robot<CODE> </CODE><CODE>3</CODE><CODE> </CODE><CODE>3</CODE><CODE> </CODE><BR><B>and</B><CODE> </CODE>r2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>crazy_txt_robot<CODE> </CODE><CODE>2</CODE><CODE> </CODE><CODE>2</CODE><CODE> </CODE><BR><B>and</B><CODE> </CODE>r3<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>obstinate_txt_robot<CODE> </CODE><CODE>1</CODE><CODE> </CODE><CODE>1</CODE><BR><B>and</B><CODE> </CODE>r4<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>interactive_txt_robot<CODE> </CODE><CODE>0</CODE><CODE> </CODE><CODE>0</CODE><BR><B>in</B><CODE> </CODE>w#add<CODE> </CODE>r1;<CODE> </CODE>w#add<CODE> </CODE>r2;<CODE> </CODE>w#add<CODE> </CODE>r3;<CODE> </CODE>w#add<CODE> </CODE>r4;<CODE> </CODE>w#run<CODE> </CODE>()<CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
We may skip, for the moment, the implementation of a graphical
interface for our world of robots. In due course, we will obtain an
application having an appearance like figure <A HREF="book-ora161.html#fig-grobots">17.12</A>.<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV> 
<DIV ALIGN=center>
<IMG SRC="book-ora077.gif">
<BR>
<BR>
<DIV ALIGN=center>Figure 17.12: The graphical world of robots</DIV><BR>

<A NAME="fig-grobots"></A>
</DIV>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE><A NAME="toc239"></A>
<H3> Graphical Robots</H3><A NAME="grch"></A>We may implement robots in a graphical mode by following the same
approach as with the text mode:
<OL type=1>
<LI>
 define a generic graphical object,

<LI> define an abstract class of graphical robots by double
inheritance from robots and graphical objects (analogous to the
interface class of page&nbsp;<A HREF="book-ora161.html#cspec">??</A>),

<LI> define, through double inheritance, the particular behavior 
of robots.
</OL>
<H4> Generic Graphical Objects</H4>A simple graphical object is an object possessing a <TT>display</TT>
method which takes, as arguments, the coordinates of a pixel
and displays it.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>graph_object<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>display<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE>-&gt;<CODE> </CODE>int<CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
From this specification, it would be possible to implement graphical
objects with extremely complex behavior. We will content ourselves
for now with a class <TT>graph_item</TT>, displaying a bitmap that
serves to represent the object.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>graph_item<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>im<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>size_box_x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>size_box_y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>bitmap<CODE> </CODE><CODE>=</CODE><CODE> </CODE>im<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>last<CODE> </CODE><CODE>=</CODE><CODE> </CODE>None<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>erase<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>match</B><CODE> </CODE>last<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Some<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>,</CODE>img<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>Graphics.draw_image<CODE> </CODE>img<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>None<CODE> </CODE>-&gt;<CODE> </CODE>()<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>draw<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Graphics.draw_image<CODE> </CODE>bitmap<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>keep<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>last<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>Some<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<CODE>,</CODE>Graphics.get_image<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE>size_box_x<CODE> </CODE>size_box_y<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>display<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>match</B><CODE> </CODE>last<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Some<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>,</CODE>img<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><B>if</B><CODE> </CODE>x<CODE>&lt;&gt;</CODE>i<CODE> </CODE><CODE>||</CODE><CODE> </CODE>y<CODE>&lt;&gt;</CODE>j<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><CODE> </CODE><TT>(</TT><CODE> </CODE>self#erase<CODE> </CODE>;<CODE> </CODE>self#keep<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE>;<CODE> </CODE>self#draw<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>None<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT><CODE> </CODE>self#keep<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE>;<CODE> </CODE>self#draw<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
An object of <TT>graph_item</TT> stores the portion of the image
upon which it is drawn in order to restore it in subsequent redraws. 
In addition, if the image has not been moved, it will not be
redrawn.<BR>
<BR>


<PRE><BR># <B>let</B><CODE> </CODE>foo_bitmap<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><CODE>[|[|</CODE><CODE> </CODE>Graphics.black<CODE> </CODE><CODE>|]|]</CODE><CODE> </CODE>;;<BR># <B>class</B><CODE> </CODE>square_item<CODE> </CODE>x<CODE> </CODE>col<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>graph_item<CODE> </CODE>x<CODE> </CODE>x<CODE> </CODE><TT>(</TT>Graphics.make_image<CODE> </CODE>foo_bitmap<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>draw<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>col<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><TT>(</TT>i<CODE>+</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><TT>(</TT>j<CODE>+</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><TT>(</TT>x<CODE>-</CODE><CODE>2</CODE><TT>)</TT><CODE> </CODE><TT>(</TT>x<CODE>-</CODE><CODE>2</CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE>disk_item<CODE> </CODE>r<CODE> </CODE>col<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>graph_item<CODE> </CODE><TT>(</TT><CODE>2</CODE><CODE>*</CODE>r<TT>)</TT><CODE> </CODE><TT>(</TT><CODE>2</CODE><CODE>*</CODE>r<TT>)</TT><CODE> </CODE><TT>(</TT>Graphics.make_image<CODE> </CODE>foo_bitmap<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>draw<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>col<CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_circle<CODE> </CODE><TT>(</TT>i<CODE>+</CODE>r<TT>)</TT><CODE> </CODE><TT>(</TT>j<CODE>+</CODE>r<TT>)</TT><CODE> </CODE><TT>(</TT>r<CODE>-</CODE><CODE>2</CODE><TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE>file_bitmap_item<CODE> </CODE>name<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>ch<CODE> </CODE><CODE>=</CODE><CODE> </CODE>open_in<CODE> </CODE>name<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>let</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Marshal.from_channel<CODE> </CODE>ch<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>let</B><CODE> </CODE>y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Marshal.from_channel<CODE> </CODE>ch<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>let</B><CODE> </CODE>im<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Marshal.from_channel<CODE> </CODE>ch<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>close_in<CODE> </CODE>ch<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>graph_item<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><TT>(</TT>Graphics.make_image<CODE> </CODE>im<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
We specialize the <TT>graph_item</TT> with instances of crosses,
disks, and other bitmaps, read from a file.<BR>
<BR>

<H5> The abstract graphical robot</H5> is both a robot and a
graphical object.
<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>graph_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>graph_object<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>

<H5> Graphical robots that are fixed, crazy, and obstinate</H5> are
specialized graphical objects.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>fix_graph_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>fix_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>disk_item<CODE> </CODE><CODE>7</CODE><CODE> </CODE>Graphics.green<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE>crazy_graph_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>crazy_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>file_bitmap_item<CODE> </CODE><CODE>"crazy_bitmap"</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE>obstinate_graph_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>obstinate_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>square_item<CODE> </CODE><CODE>1</CODE><CODE>5</CODE><CODE> </CODE>Graphics.black<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>

<H5> The interactive graphical robot</H5> uses the primitives
<TT>key_pressed</TT> and <TT>read_key</TT> of module
<TT>Graphics</TT> to determine its next move. We again see the
key presses <TT>8</TT>, <TT>6</TT>, <TT>2</TT> and <TT>4</TT> on the
numeric keypad (<CODE>NumLock</CODE> button active). In this manner, the
user is not obliged to provide direction at each
step in the simulation. <BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>interactive_graph_robot<CODE> </CODE>i0<CODE> </CODE>j0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>interactive_robot<CODE> </CODE>i0<CODE> </CODE>j0<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>file_bitmap_item<CODE> </CODE><CODE>"interactive_bitmap"</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>get_move<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>not<CODE> </CODE><TT>(</TT>Graphics.key_pressed<CODE> </CODE>()<TT>)</TT><CODE> </CODE><B>then</B><CODE> </CODE>Nothing<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><B>match</B><CODE> </CODE>Graphics.read_key()<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>'8'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>North<CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'2'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>South<CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'4'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>West<CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'6'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>East<CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>Nothing<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
<A NAME="toc240"></A>
<H3> Graphical World</H3><A NAME="gwch"></A>
We obtain a world with a graphical interface by inheriting from the pure
world, instantiating the parameter <CODE>'a_robot</CODE> with the graphical
robot abstract class <TT>graph_robot</TT>. As with the text mode
world, the graphical world provides its own method, <TT>run_robot</TT>,
to implement the robot's behavior as well as the general activation
method <TT>run</TT>.<BR>
<BR>


<PRE><BR># <B>let</B><CODE> </CODE>delay<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Sys.time<CODE> </CODE>()<CODE> </CODE><B>in</B><CODE> </CODE><B>while</B><CODE> </CODE><TT>(</TT>Sys.time<CODE> </CODE>()<TT>)</TT><CODE> </CODE><CODE>-.</CODE><CODE> </CODE>t<CODE> </CODE><CODE>&lt;</CODE><CODE> </CODE>x<CODE> </CODE><B>do</B><CODE> </CODE>()<CODE> </CODE><B>done</B><CODE> </CODE>;;<BR><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>graph_world<CODE> </CODE>l0<CODE> </CODE>h0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE>graph_robot<CODE>]</CODE><CODE> </CODE>world<CODE> </CODE>l0<CODE> </CODE>h0<CODE> </CODE><B>as</B><CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>initializer</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>gl<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>l<CODE>+</CODE><CODE>2</CODE><TT>)</TT><CODE>*</CODE><CODE>1</CODE><CODE>5</CODE><CODE> </CODE><B>and</B><CODE> </CODE><CODE> </CODE>gh<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>h<CODE>+</CODE><CODE>2</CODE><TT>)</TT><CODE>*</CODE><CODE>1</CODE><CODE>5</CODE><CODE> </CODE><B>and</B><CODE> </CODE>lw<CODE>=</CODE><CODE>7</CODE><CODE> </CODE><B>and</B><CODE> </CODE>cw<CODE>=</CODE><CODE>7</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>Graphics.open_graph<CODE> </CODE><TT>(</TT><CODE>" "</CODE><CODE>^</CODE><TT>(</TT>string_of_int<CODE> </CODE>gl<TT>)</TT><CODE>^</CODE><CODE>"x"</CODE><CODE>^</CODE><TT>(</TT>string_of_int<CODE> </CODE>gh<TT>)</TT><TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE><TT>(</TT>Graphics.rgb<CODE> </CODE><CODE>1</CODE><CODE>7</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>7</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>7</CODE><CODE>0</CODE><TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><CODE>0</CODE><CODE> </CODE>lw<CODE> </CODE>gl<CODE> </CODE>lw<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><TT>(</TT>gl<CODE>-</CODE><CODE>2</CODE><CODE>*</CODE>lw<TT>)</TT><CODE> </CODE><CODE>0</CODE><CODE> </CODE>lw<CODE> </CODE>gh<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><CODE>0</CODE><CODE> </CODE><TT>(</TT>gh<CODE>-</CODE><CODE>2</CODE><CODE>*</CODE>cw<TT>)</TT><CODE> </CODE>gl<CODE> </CODE>cw<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE>lw<CODE> </CODE><CODE>0</CODE><CODE> </CODE>lw<CODE> </CODE>gh<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>run_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r#next_pos<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>delay<CODE> </CODE><CODE>0</CODE><CODE>.</CODE><CODE>0</CODE><CODE>0</CODE><CODE>1</CODE><CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>self#is_legal<CODE> </CODE>p<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>self#is_free<CODE> </CODE>p<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><CODE> </CODE><TT>(</TT><CODE> </CODE>r#set_pos<CODE> </CODE>p<CODE> </CODE>;<CODE> </CODE>self#display_robot<CODE> </CODE>r<TT>)</TT><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>display_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>r#get_pos<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>r#display<CODE> </CODE><TT>(</TT>i<CODE>*</CODE><CODE>1</CODE><CODE>5</CODE><CODE>+</CODE><CODE>1</CODE><CODE>5</CODE><TT>)</TT><CODE> </CODE><TT>(</TT>j<CODE>*</CODE><CODE>1</CODE><CODE>5</CODE><CODE>+</CODE><CODE>1</CODE><CODE>5</CODE><TT>)</TT><CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>run()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>List.iter<CODE> </CODE>self#display_robot<CODE> </CODE>robots<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>super#run()<CODE> </CODE><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
Note that the graphical window is created at the time that an object
of this class is initialized.<BR>
<BR>

<H5> The rectangular planar graphical world</H5> is obtained in much
the same manner as with the rectangular planar textual world.<BR>
<BR>


<PRE><BR># <B>class</B><CODE> </CODE>closed_graph_world<CODE> </CODE>l0<CODE> </CODE>h0<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>graph_world<CODE> </CODE>l0<CODE> </CODE>h0<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>is_legal<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>j<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE>0</CODE><CODE>&lt;=</CODE>i<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>i<CODE>&lt;</CODE>l<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT><CODE>0</CODE><CODE>&lt;=</CODE>j<TT>)</TT><CODE> </CODE><CODE>&amp;</CODE><CODE> </CODE><TT>(</TT>j<CODE>&lt;</CODE>h<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class closed_graph_world :</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    val h : int</CODE><BR><CODE>    val l : int</CODE><BR><CODE>    val mutable robots : graph_robot list</CODE><BR><CODE>    method add : graph_robot -&gt; unit</CODE><BR><CODE>    method display_robot : graph_robot -&gt; unit</CODE><BR><CODE>    method is_free : int * int -&gt; bool</CODE><BR><CODE>    method is_legal : int * int -&gt; bool</CODE><BR><CODE>    method run : unit -&gt; unit</CODE><BR><CODE>    method run_robot : graph_robot -&gt; unit</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
We may then test the graphical application by typing in:<BR>
<BR>


<PRE><BR><B>let</B><CODE> </CODE>w<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>closed_graph_world<CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE>;;<BR>w#add<CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>fix_graph_robot<CODE> </CODE><CODE>3</CODE><CODE> </CODE><CODE>3</CODE><TT>)</TT><CODE> </CODE>;;<BR>w#add<CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>crazy_graph_robot<CODE> </CODE><CODE>2</CODE><CODE> </CODE><CODE>2</CODE><TT>)</TT><CODE> </CODE>;;<BR>w#add<CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>obstinate_graph_robot<CODE> </CODE><CODE>1</CODE><CODE> </CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE>;;<CODE> </CODE><BR>w#add<CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>interactive_graph_robot<CODE> </CODE><CODE>5</CODE><CODE> </CODE><CODE>5</CODE><TT>)</TT><CODE> </CODE>;;<BR>w#run<CODE> </CODE>()<CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
<A NAME="toc241"></A>
<H3> To Learn More</H3>
The implementation of the method <TT>run_robot</TT> in different
worlds suggests that the robots are potentially able to move to any
point on the world the moment it is empty and legal. Unfortunately,
nothing prevents a robot from modifying its position arbitrarily; the
world cannot prevent it. One remedy would consist of having robot
positions being controlled by the world; when a robot attempts to
move, the world verifies not only that the new position is legal,
but also that it constitutes an authorized move. In that
case, the robot must be capable of asking the world its actual
position, with the result that the robot class must become dependent
on the world's class. The robot class would take, as a type
parameter, the world class.<BR>
<BR>
This modification permits defining robots capable of querying the
world in which they run, thus behaving as dependents of the world. We
may then implement robots which follow or avoid other robots, try to
block them, and so forth.<BR>
<BR>
Another extension would be to permit robots to communicate with one
another, exchanging information, perhaps constituting themselves into
teams of robots.<BR>
<BR>
The chapters of the next section allow making execution of robots
independent from one another: by making use of <TT>Threads</TT> (see
page <A HREF="index.html#chap-PC">??</A>), each may execute as a distinct process. They
may profit from the possibilities of distributed computing (see
<A HREF="index.html#chap-PD">??</A>) where the robots become <EM>clients</EM> executing on
remote machines that announce their movements or request other
information from a world that behaves as a <EM>server</EM>. This problem
is dealt with on page <A HREF="book-ora195.html#app-robby">??</A>.<BR>
<BR>


<BR>
<BR>
<BR>
<BR>
<HR>
<A HREF="book-ora160.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora162.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
